/********************************************************************
 * Filename:	Testing.c
 * Description:	The testing interface.
 * Group 2:		nachOS
 * Author(s):	Daniel Fairweather
 *              Ying Wang
 *              Jan Durakiewicz
 * Class:		CSE 325
 * Instructor:	David Duggan
 * Assignment:	Lab #6 Page Replacement
 * Assigned:	4/2/2013
 * Due:			4/9/2013
 ********************************************************************/
 


#include "Testing.h"
#include "BitOps.h"
#include "MemoryManager.h"

int testMode = 0;

/* Command Variables */
char command[100];      /* The command entered by the user. */
char args[10][100];     /* The arguments of the command. */
char argc;              /* The number of arguments provided. */
char result[100];       /* The result of the command. */
char comment[100];      /* A comment. */



int main(){
    int isCommand = 0;
    init();

    while(1){
        /* Dynamic Mode Printing and Clearing */
        if(testMode == 0){
            clearScreen();
            /* Print Modules */
            printSystemModule();
            printSystemDataStructureModule();
            printUserDataStructureModule();
			printLRUModule();
            printPageTablesModule();
            printResultModule();
            printdiv();
        }
        
		if(testMode != 2){
			printf(">>> ");
		}
        isCommand = getCommand();
        if(testMode == 2 && isCommand == 1){
            int i = 0;
			if(testMode == 2){
				printf(">>> ");
			}
            printf("%s", command);
            while(i < argc){
                printf(" %s", args[i]);
                i++;
            }
            printf("\n");
        }
        else if(testMode == 2 && isCommand == 0){
            printf("%s", comment);
        }
        if(isCommand == 1){
            setResult(runCommand(command, args, argc));
        }
    }
}


void clearScreen(){
#ifdef _WIN32
    system("cls");
    
#else 
    system("clear");
    
#endif
}



void printSystemModule(){
    printdiv();
    printf("OS Name: nachOS\n");
    printf("Group #: 2\n");
}



void printResultModule(){
    int i = 0;
    
    printdiv();
    printf("Previous Command: %s", command);
    while(i < argc){
        printf(" %s", args[i]);
        i++;
    }
    printf("\n");
    printf("Result:           %s\n", result);
}

void printLRUModule(){
	Linked_List_Node* node = head;
	int i = 0;

	printdiv();
	printf("LRU STACK:\t");
	if(numNodes != 0){
		while(i < numNodes - 1){
			printf("%i, ", node->value+56);
			if(node->value+56 < 100){
				printf(" ");
			}
			if((i+1)%6 == 0){
				printf("\n\t\t");
			}
			node = node->next;
			i++;
		}
		printf("%i\n", node->value+56);
	}
	else{
		printf("Empty\n");
	}
}



void printdiv(){
    if(testMode == 0){
        printf("-------------------------------------------------------------------------\n");
    }
}



int getCommand(){
    char buffer[1000];
    int i, j, k;
    
    /* Get a string from the user, then parse the command and it's arguments. */
    while(fgets(buffer, 1000, stdin) == NULL);
    
    
    /* If this is a comment, don't parse anything else. */
    if(buffer[0] == '*' || buffer[0] == '\n'){
        for(i = 0; i < strlen(buffer); i++){
            comment[i] = buffer[i];
        }
        comment[i] = '\0';
        return(0);
    }
    
    /* Normalize the data */
    for(i = 0; i < strlen(buffer); i++){
        buffer[i] = tolower(buffer[i]);
    }
    buffer[strlen(buffer) - 1] = '\0';
    argc = 0;
    
    /* Parse the command. */
    for(i = 0; i < strlen(buffer); i++){
        if(buffer[i] == ' '){
            break;
        }
        command[i] = buffer[i];
    }
    command[i] = '\0';
    i++;
    
    /* Parse the arguments. */
    for(j = 0; j < 10, i < strlen(buffer); j++){
        /* Parse a normal argument. */
        for(k = 0; i < strlen(buffer), k < 100; i++, k++){
            if(buffer[i] == ' '){
                break;
            }
            args[j][k] = buffer[i];
        }
        args[j][k] = '\0';
        argc++;
        i++;
    }
    
    return(1);
}



void setResult(char* string){
    strcpy(result, string);
    if(testMode == 1 || testMode == 2){
        printf("    %s\n", result);
    } 
}



void printUserDataStructureModule(){
    printdiv();
    printf("USER FRAMES:\t");
    list_user();        
}



void printSystemDataStructureModule(){
    printdiv();
    printf("SYSTEM FRAMES:\t");
    list_system();
}



void printPageTablesModule(){
    printdiv();
    printf("PAGE TABLES:\t");
    list_all_pagetables();
    
}


void list_all_pagetables(){
    int i, j;
    int firstRow = 1;
    //PAGE TABLE (metatable index)
    //         from metatable     from metatable  | from page table  | from swap (from swap)
    for(i = 0; i < 100; i++){
        if(metaTable.row[i][0] < 16384){ //if it's a valid address
            if(firstRow == 1){
				printf("LOGICAL PAGE\tPHYSICAL PAGE\tFRAME IN RAM\n");
                firstRow = 0;
            }
            else{
                printf("\n");
            }
            list_pagetable(i);
        } 
    }
    if(firstRow == 1){
        printf("Empty\n");
    }
}



void list_system(){
    printf("FRAME NUMBER\tSYSTEM USAGE \n");
    printf("\t\t0 - 29\t\tReserved for IPC and Process Manager \n");
    printf("\t\t30 - 55\t\tReserved for Page tables \n");
}



void list_user(){
    int i = 56;
	printf("FRAME NUMBER\tPHYSICAL PAGE NUMBER\n");
    for(i = 56; i <= 255; i++){
        if(swapTable.row[i-56] != 16384){
           printf("\t\t%d\t\t%d\n", i, swapTable.row[i-56]);
        }
    }
}



void list_pagetable(int tableID){
    int i = 0;
    if(metaTable.row[tableID][0] == BS_SIZE/FRAME_SIZE){
        printf("\t\tPagetable doesn't exist!");
    }
    else{
        printf("Pagetable %d\t", tableID);
        for(i = metaTable.row[tableID][0]; i <= metaTable.row[tableID][1]; i++){
            if(metaTable.row[tableID][1] < BS_SIZE/FRAME_SIZE){
                if(i != metaTable.row[tableID][0]){
                    printf("\t\t");
                }
                printf("%d\t\t%d\t\t", i, get_page_address(&pageTable.row[i]));
                if(is_in_swaptable(get_page_address(&pageTable.row[i])) == -1){
                    printf("Invalid\n");
                }
                else{
                    printf("%d\n", is_in_swaptable(get_page_address(&pageTable.row[i]))+56);
                }
            }
        }
    }
}



void print_useTable(){
	short unsigned int i;
	for(i = 0; i < USE_TABLE_SIZE; i++)
	{
		if(i % 4 == 0)
			printf("--");
		if(i % (sizeof(unsigned long) * 8) == 0)
			printf("\n");
		printf("%d|",get_use_table_at(i));
	}
}



void print_binary(short unsigned int n){
	if(n == 0 || n == 1)
		printf("%d",n);
	else{
		print_binary(n >> 1);
		printf("%d",n & 0x1);
	}
}
